#pragma once
#include</usr/include/jsoncpp/json/json.h>
#include</usr/include/mysql/mysql.h>
#include</usr/include/websocketpp/server.hpp>
#include</usr/include/websocketpp/config/asio_no_tls.hpp>
#include<vector>
#include<string>
#include<memory>
#include<sstream>
#include<fstream>
#include"logger.hpp"


typedef websocketpp::server<websocketpp::config::asio> wsserver_t;
class mysql_util
{
    public:
    static MYSQL* mysql_create(
        std::string& host,
        std::string& user,
        std::string& pass,
        std::string& db,
        uint16_t port = 3306
        )
    {
        //1.创建一个MYSQL句柄
        MYSQL* mysql=mysql_init(nullptr);
        if(mysql==NULL)
        {
            ERR_LOG("mysql_init failed !");
            return nullptr;
        }
        //2.连接MYSQL服务器
        MYSQL* ret=mysql_real_connect(mysql,host.c_str(),user.c_str(),pass.c_str(),db.c_str(),port,nullptr,0);
        if(ret==nullptr)
        {
            ERR_LOG("mysql_real_connect failed %s!",mysql_error(ret));
            mysql_close(ret);
            return nullptr;
        }
        //3.设置字符集
        int res=mysql_set_character_set(mysql, "utf8");
        if(res!=0)
        {
            ERR_LOG("mysql_set_character_set %s!",mysql_error(mysql));
            mysql_close(mysql);
            return nullptr;
        }
        return mysql;
    }
    static bool mysql_exc(MYSQL* mysql,std::string& stmt_str)
    {
        int ret=mysql_query(mysql, stmt_str.c_str());
        if(ret!=0)
        {
            ERR_LOG("%s\n",stmt_str.c_str());
            ERR_LOG("mysql_exc fail!! %s ",mysql_error(mysql));
            return false;
        }
        return true;
    }
    static void mysql_destory(MYSQL* mysql)
    {
        if (mysql != NULL) 
        {
            mysql_close(mysql);
        }
        return ;
    }
};

class json_util
{
    public:
    //序列化
    static bool Serialize(Json::Value& value,std::string& str)
    {
        //1.实例化一个工厂类对象StreamWriterBuilder
        Json::StreamWriterBuilder builder;
        //2.利用工厂类实例化一个StreamWriterBuilder对象
        std::unique_ptr<Json::StreamWriter> sw(builder.newStreamWriter());  
        //3.创建一个字符流，并将实例化的结果写入其中：
        std::stringstream ss;
        int ret=sw->write(value,&ss);
        if(ret!=0)
        {
            ERR_LOG("json serialize failed!!");
            return false;
        }
        str=ss.str();
        return true;
    }
    //反序列化
    static bool Unserialize(const std::string& str,Json::Value& value)
    {
        //1.实例化一个工厂类对象
        Json::CharReaderBuilder builder;
        //2.利用工厂类实例化一个CharReader对象
        std::unique_ptr<Json::CharReader> cr(builder.newCharReader());
        //3.反序列化
        std::string error;
        bool ret=cr->parse(str.c_str(),str.c_str()+str.size(),&value,&error);
        if(ret==false)
        {
            ERR_LOG("json Unserialize failed!! %s",error.c_str());
            return false;
        }
        return true;
    }
};

class string_util
{
    public:
    static int split(const std::string& src,const std::string& sep,std::vector<std::string>& res)
    {
        size_t index=0;
        while(index<src.size())
        {
            size_t pos=src.find(sep,index);
            if(pos==std::string::npos)
            {
                //找到末尾了
                res.push_back(src.substr(index));
                break;
            }
            //找到了
            if(index==pos)
            {
                index+=sep.size();
                continue;
            }
            res.push_back(src.substr(index,pos-index));
            index=pos+sep.size();
        }
        return res.size();
    }
};

class file_util
{
    public:
    static bool file_read(const std::string fname,std::string& body)
    {
        std::ifstream file(fname,std::ios::binary);
        if(file.is_open()==false)
        {
            ERR_LOG("file open fail!!");
            return false;
        }
        size_t fsize;
        file.seekg(0, std::ios::end);
        fsize = file.tellg();
        file.seekg(0, std::ios::beg);
        body.resize(fsize);
        file.read(&body[0], fsize);
        if(file.good()==false)
        {
            ERR_LOG("file read fail!!");
            file.close();
            return false;
        }
        file.close();
        return true;
    }
};